/*******************************************************************************
 * Copyright (c) 2001, 2004 IBM Corporation and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 * 
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *******************************************************************************/
package com.trainfinder.datapersistace;

import java.io.Serializable;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;

import javax.persistence.EmbeddedId;
import javax.persistence.Entity;

import org.hibernate.annotations.NamedQuery;

import com.trainfinder.requestor.IJourney;
import com.trainfinder.requestor.JourneyPk;

@Entity
@org.hibernate.annotations.NamedQueries( {

		@NamedQuery(name = "get.journey", query = "select j from Journey j where j.toStation = :toStation and j.fromStation = :fromStation and "
				+ "( j.weekdayPence > 0 or j.weekendPence > 0 )  and  j.id.date >= :dateAfter and j.id.date <= :dateTo and "
				+ "ticketType = :ticketType ORDER BY  j.id.date", cacheable = true),

		@NamedQuery(name = "get.single.journey", query = "select j from Journey j where j.id.ticketType = :ticketType and j.id.ticketClass = :ticketClass and "
				+ "j.id.outwardOrReturn = :outwardOrReturn  and j.id.date = :date", cacheable = true),

		@NamedQuery(name = "remove-expired-data", query = "select j from Journey j where j.id.date <= :date ", cacheable = true),
		@NamedQuery(name = "remove-old-lastupdated", query = "select j from Journey j where   j.toStation = :toStation and j.fromStation = :fromStation and j.lastUpdatedWeekdayPrice < :lastUpdated and j.lastUpdatedWeekendPrice < :lastUpdated", cacheable = true) })
public class Journey implements Serializable, IJourney {

	private static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat(
			"yyyy-MM-dd");

	public static final Date NULL_DATE = new Date(0);

	@EmbeddedId
	public JourneyPk id = new JourneyPk();

	private Date lastUpdatedWeekdayPrice = NULL_DATE;

	private Date lastUpdatedWeekendPrice = NULL_DATE;

	public boolean hasSetWeekdayPrice() {
		return lastUpdatedWeekdayPrice != NULL_DATE;
	}

	public boolean hasSetWeekendPrice() {
		return lastUpdatedWeekendPrice != NULL_DATE;
	}

	private String fromStation;

	private String toStation;

	private int durationMin;

	private int durationHour;

	private int arivalMin;

	private int arivalHour;

	private int departureMin;

	private int departureHour;

	private int weekdayPence;

	private int weekendPence;

	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;

	public static long getSerialVersionUID() {
		return serialVersionUID;
	}

	public JourneyPk getId() {
		return id;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see com.trainfinder.datapersistace.IJourney#getToStation()
	 */
	public String getToStation() {
		return toStation;
	}

	public void setFromStation(String fromStation) {
		this.fromStation = fromStation;
	}

	public void setLastUpdatedWeekendPrice(Date lastUpdated) {
		this.lastUpdatedWeekendPrice = (Date) lastUpdated.clone();
	}

	public void setLastUpdatedWeekdayPrice(Date lastUpdated) {
		this.lastUpdatedWeekdayPrice = (Date) lastUpdated.clone();
	}

	public void setToStation(String to) {
		this.toStation = to;
	}

	public void setDepartureHour(int departureHour) {
		this.departureHour = departureHour;
	}

	public void setDepartureMin(int departureMin) {
		this.departureMin = departureMin;
	}

	public void setArivalHour(int arivalHour) {
		this.arivalHour = arivalHour;
	}

	public void setArivalMin(int arivalMin) {
		this.arivalMin = arivalMin;
	}

	public void setDurationHour(int durationHour) {
		this.durationHour = durationHour;
	}

	public void setDurationMin(int durationMin) {
		this.durationMin = durationMin;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see com.trainfinder.datapersistace.IJourney#getArivalHour()
	 */
	public int getArivalHour() {
		return arivalHour;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see com.trainfinder.datapersistace.IJourney#getArivalMin()
	 */
	public int getArivalMin() {
		return arivalMin;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see com.trainfinder.datapersistace.IJourney#getDepartureHour()
	 */
	public int getDepartureHour() {
		return departureHour;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see com.trainfinder.datapersistace.IJourney#getDepartureMin()
	 */
	public int getDepartureMin() {
		return departureMin;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see com.trainfinder.datapersistace.IJourney#getDurationHour()
	 */
	public int getDurationHour() {
		return durationHour;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see com.trainfinder.datapersistace.IJourney#getDurationMin()
	 */
	public int getDurationMin() {
		return durationMin;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see com.trainfinder.datapersistace.IJourney#getFromStation()
	 */
	public String getFromStation() {
		return fromStation;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see com.trainfinder.datapersistace.IJourney#getLastUpdated()
	 */
	public Date getLastUpdatedWeekdayPrice() {
		return (Date) lastUpdatedWeekdayPrice.clone();
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see com.trainfinder.datapersistace.IJourney#toString()
	 */
	public String toString() {
		return "ticketType=" + id.getTicketType() + ",ticketClass"
				+ id.getTicketClass() + ",outwardOrReturn="
				+ id.getOutwardOrReturn() + ",date=" + id.getDate() + ",pence="
				+ weekdayPence + ",lastUpdatedWeekdayPrice="
				+ DATE_FORMAT.format(lastUpdatedWeekdayPrice) + ",lastUpdatedWeekendPrice="
				+ DATE_FORMAT.format(lastUpdatedWeekendPrice) + ",fromStation="
				+ fromStation + ",toStation=" + toStation + ",durationMin="
				+ durationMin + ",durationHour=" + durationHour + ",arivalMin="
				+ arivalMin + ",arivalHour=" + arivalHour + ",departureMin="
				+ departureMin + ",departureHour=" + departureHour

		;
	}

	public char getOutwardOrReturn() {

		return id.getOutwardOrReturn();
	}

	public void setOutwardOrReturn(char outwardOrReturn) {
		id.setOutwardOrReturn(outwardOrReturn);
	}

	public void setWeekdayPence(int pence) {
		this.weekdayPence = pence;
		setLastUpdatedWeekdayPrice(new Date());
	}

	public void setWeekendPence(int pence) {
		this.weekendPence = pence;
		setLastUpdatedWeekendPrice(new Date());
	}

	public int getWeekdayPence() {
		return this.weekdayPence;
	}

	public int getWeekendPence() {
		return this.weekendPence;
	}

	public IJourney clone() {

		final Journey result;
		try {
			result = (Journey) super.clone();
			result.id = id;
			result.lastUpdatedWeekdayPrice = lastUpdatedWeekdayPrice;
			result.lastUpdatedWeekendPrice = lastUpdatedWeekendPrice;
			result.fromStation = fromStation;
			result.toStation = toStation;
			result.durationMin = durationMin;
			result.durationHour = durationHour;
			result.arivalMin = arivalMin;
			result.arivalHour = arivalHour;
			result.departureMin = departureMin;
			result.departureHour = departureHour;
			result.weekdayPence = weekdayPence;
			result.weekendPence = weekendPence;
			return result;
		} catch (CloneNotSupportedException e) {
			throw new Error("This should never happen!");
		}

	}

	public Date getLastUpdatedWeekendPrice() {
		return (Date) lastUpdatedWeekendPrice.clone();
	}

}
